import { ChangeDetectorRef, Component, DestroyRef, inject, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { finalize } from 'rxjs';

import { ActionCode } from '@app/config/actionCode';
import { RequestParams } from '@app/core/domain/request-params';
import { MenusService } from '@app/core/services/http/system/menus.service';
import { Menu, OptionsInterface } from '@app/core/services/types';
import { AntTableConfig } from '@app/shared/components/ant-table/ant-table.component';
import { PageHeaderType } from '@app/shared/components/page-header/page-header.component';
import { TreeNodeInterface } from '@app/shared/components/tree-table/tree-table.component';
import { MapKeyType, MapPipe, MapSet } from '@app/shared/pipes/map.pipe';
import { SharedModule } from '@app/shared/shared.module';
import { fnFlatDataHasParentToTree, fnFlattenTreeDataByDataList, getAllChildrenNodes, getAllParentNodes, searchTreeByKey } from '@app/utils/treeTableTools';
import { ModalBtnStatus } from '@app/widget/base-modal';
import { MenuModalService } from '@app/widget/biz-widget/system/menu-modal/menu-modal.service';
import { isBoolean, uniqBy } from 'lodash';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzTableQueryParams } from 'ng-zorro-antd/table';

interface PageSearchParam {
  Name: string;
  Status?: boolean;
}

@Component({
  selector: 'app-menu',
  standalone: true,
  imports: [SharedModule],
  templateUrl: './menu.component.html',
  styleUrl: './menu.component.less'
})
export class MenuComponent implements OnInit {
  @ViewChild('zorroIconTpl', { static: true }) zorroIconTpl!: TemplateRef<NzSafeAny>;
  @ViewChild('aliIconTpl', { static: true }) aliIconTpl!: TemplateRef<NzSafeAny>;
  @ViewChild('operationTpl', { static: true }) operationTpl!: TemplateRef<NzSafeAny>;
  @ViewChild('visibleTpl', { static: true }) visibleTpl!: TemplateRef<NzSafeAny>;
  @ViewChild('newLinkFlag', { static: true }) newLinkFlag!: TemplateRef<NzSafeAny>;
  @ViewChild('highLightTpl', { static: true }) highLightTpl!: TemplateRef<NzSafeAny>;
  ActionCode = ActionCode;
  pageSearchParam: Partial<PageSearchParam> = {};
  destroyRef = inject(DestroyRef);
  tableConfig!: AntTableConfig;
  pageHeaderInfo: Partial<PageHeaderType> = {
    title: '菜单管理',
    breadcrumb: ['首页', '功能管理', '菜单管理']
  };
  dataList: TreeNodeInterface[] = [];
  visibleOptions: OptionsInterface[] = [];
  highLightText: SafeHtml = '';
  constructor(
    private readonly message: NzMessageService,
    private readonly menuService: MenusService,
    private readonly cdr: ChangeDetectorRef,
    private readonly menuModalService: MenuModalService,
    private readonly modalSrv: NzModalService,
    private readonly sanitizer: DomSanitizer
  ) {}

  reloadTable(): void {
    this.message.info('已经刷新了');
    this.getDataList();
  }

  tableChangeDectction(): void {
    this.dataList = [...this.dataList];
    this.cdr.detectChanges();
  }

  tableLoading(isLoading: boolean): void {
    this.tableConfig.loading = isLoading;
    this.tableChangeDectction();
  }

  appendRequestParams(): RequestParams {
    const filter: Partial<Menu> = {};
    let requestParams: RequestParams = {
      '@relationships': 'all',
      '@filter': '',
      ...filter
    };

    return requestParams;
  }

  handleFilterByPageSearch(result: Menu[]): Menu[] {
    let filterResult: Menu[] = result;
    if (this.pageSearchParam.Name) {
      this.highLightText = this.sanitizer.bypassSecurityTrustHtml(this.pageSearchParam.Name);
      filterResult = uniqBy(searchTreeByKey(result, 'menuname', this.pageSearchParam.Name), r => r.id);
    }

    if (isBoolean(this.pageSearchParam.Status)) {
      filterResult = searchTreeByKey(result, 'status', this.pageSearchParam.Status);
    }

    return filterResult;
  }

  getDataList(e?: NzTableQueryParams): void {
    this.tableConfig.loading = true;
    const params: RequestParams = this.appendRequestParams();
    this.menuService
      .getEntityList(params)
      .pipe(
        finalize(() => {
          this.tableLoading(false);
        }),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(menuList => {
        let target = fnFlatDataHasParentToTree(this.handleFilterByPageSearch(menuList), 'fatherid');
        this.dataList = fnFlattenTreeDataByDataList(target);
        this.tableLoading(false);
      });
  }

  resetForm(): void {
    this.pageSearchParam = {};
    this.getDataList();
  }

  add(fatherId: number): void {
    this.menuModalService
      .show({ nzTitle: '新增' })
      .pipe(
        finalize(() => {
          this.tableLoading(false);
        }),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(res => {
        if (!res || res.status === ModalBtnStatus.Cancel) {
          return;
        }
        const param = { ...res.modalValue };
        param.fatherId = fatherId;
        this.tableLoading(true);
        this.addEditData(param, 'addEntity');
      });
  }

  addEditData(param: Menu, methodName: 'editEntity' | 'addEntity'): void {
    this.menuService[methodName]([param])
      .pipe(
        finalize(() => {
          this.tableLoading(false);
        }),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(() => {
        this.getDataList();
      });
  }

  del(id: number): void {
    this.modalSrv.confirm({
      nzTitle: '确定要删除吗？',
      nzContent: '删除后不可恢复',
      nzOnOk: () => {
        this.tableLoading(true);
        this.menuService
          .delEntities([id])
          .pipe(
            finalize(() => {
              this.tableLoading(false);
            }),
            takeUntilDestroyed(this.destroyRef)
          )
          .subscribe(() => {
            if (this.dataList.length === 1) {
              this.tableConfig.pageIndex--;
            }
            this.getDataList();
          });
      }
    });
  }

  edit(id: number, fatherId: number): void {
    this.menuService
      .getEntityById(id)
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(res => {
        this.menuModalService
          .show({ nzTitle: '编辑' }, res[0])
          .pipe(
            finalize(() => {
              this.tableLoading(false);
            }),
            takeUntilDestroyed(this.destroyRef)
          )
          .subscribe(({ modalValue, status }) => {
            if (status === ModalBtnStatus.Cancel) {
              return;
            }
            modalValue.id = id;
            modalValue.fatherId = fatherId;
            this.tableLoading(true);
            this.addEditData(modalValue, 'editEntity');
          });
      });
  }

  changePageSize(e: number): void {
    this.tableConfig.pageSize = e;
  }

  private initTable(): void {
    this.tableConfig = {
      headers: [
        {
          title: '菜单名称',
          width: 230,
          field: 'menuname',
          tdTemplate: this.highLightTpl
        },
        {
          title: 'zorro图标',
          field: 'icon',
          width: 100,
          tdTemplate: this.zorroIconTpl
        },
        {
          title: '阿里图标',
          field: 'alicon',
          width: 100,
          tdTemplate: this.aliIconTpl
        },
        {
          title: '权限码',
          field: 'code',
          width: 300
        },
        {
          title: '路由地址',
          field: 'path',
          width: 300
        },
        {
          title: '排序',
          field: 'ordernum',
          width: 80
        },
        {
          title: '状态',
          field: 'status',
          pipe: 'available',
          width: 100
        },
        {
          title: '展示',
          field: 'visible',
          pipe: 'isOrNot',
          tdTemplate: this.visibleTpl,
          width: 100
        },
        {
          title: '外链',
          field: 'newlinkflag',
          pipe: 'isOrNot',
          tdTemplate: this.newLinkFlag,
          width: 100
        },
        {
          title: '创建时间',
          field: 'createtime',
          pipe: 'date:yyyy-MM-dd HH:mm',
          width: 180
        },
        {
          title: '操作',
          tdTemplate: this.operationTpl,
          width: 180,
          fixed: true,
          fixedDir: 'right'
        }
      ],
      total: 0,
      showCheckbox: false,
      loading: false,
      pageSize: 10,
      pageIndex: 1
    };
  }

  ngOnInit(): void {
    this.initTable();
    this.visibleOptions = [...MapPipe.transformMapToArray(MapSet.available, MapKeyType.Boolean)];
  }
}
